import express from 'express'
import cors from 'cors'
import dotenv from 'dotenv'
import { createServer } from 'http'
import { Server } from 'socket.io'
import { fileURLToPath } from 'url'
import { dirname, join } from 'path'

// 获取当前文件路径
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

// 加载环境变量
dotenv.config({ path: join(__dirname, '.env') })

// 导入 USDT 精度配置（统一设置，只设置一次）
import { USDT_PRECISION, USDT_DECIMALS } from './config.js'

// 导入路由
import authRoutes from './routes/auth.js'
import walletRoutes from './routes/wallet.js'
import transactionRoutes from './routes/transactions.js'
import c2cRoutes from './routes/c2c.js'
import chatRoutes from './routes/chat.js'
import identityRoutes from './routes/identity.js'
import { monitorTransactions } from './services/web3.js'
import db, { initDatabase, generateId } from './db/database.js'
import { authenticateSocket } from './middleware/auth.js'

const app = express()
const httpServer = createServer(app)
const io = new Server(httpServer, {
  cors: {
    origin: process.env.CORS_ORIGIN || '*',
    methods: ['GET', 'POST']
  }
})

const PORT = process.env.PORT || 9011

// 中间件
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: true }))

// 静态文件服务（用于访问上传的图片）
app.use('/uploads', express.static(join(__dirname, 'uploads')))

// 请求日志
app.use((req, res, next) => {
  console.log(`${new Date().toISOString()} - ${req.method} ${req.path}`)
  next()
})

// 初始化数据库
initDatabase()

// 路由
app.use('/api/auth', authRoutes)
app.use('/api/wallet', walletRoutes)
app.use('/api/transactions', transactionRoutes)
app.use('/api/c2c', c2cRoutes)
app.use('/api/chat', chatRoutes)
app.use('/api/identity', identityRoutes)

// 健康检查
app.get('/api/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString() })
})

// 错误处理
app.use((err, req, res, next) => {
  console.error('Error:', err)
  res.status(err.status || 500).json({
    code: err.status || 500,
    message: err.message || 'Internal Server Error',
    success: false
  })
})

// 启动服务器时加载所有需要监控的地址
async function loadMonitoringAddresses() {
  try {
    const wallets = db.prepare('SELECT user_id, currency, chain, address FROM wallets').all()
    console.log(`\n📦 加载 ${wallets.length} 个钱包地址进行监控...`)
    
    for (const wallet of wallets) {
      const chain = wallet.chain || 'ETH' // 兼容旧数据，默认为ETH
      console.log(`  - 加载地址: ${wallet.address} (用户: ${wallet.user_id}, 币种: ${wallet.currency}, 链: ${chain})`)
      monitorTransactions(wallet.address, wallet.user_id, wallet.currency, chain)
    }
    
    console.log(`✅ 所有钱包地址监控已启动 (共 ${wallets.length} 个地址)\n`)
  } catch (error) {
    console.error('❌ 加载监控地址失败:', error)
    console.error('错误详情:', error.message)
  }
}

// Socket.IO 聊天命名空间（低耦合设计）
const chatNamespace = io.of('/chat')

chatNamespace.use(async (socket, next) => {
  try {
    const token = socket.handshake.auth.token || socket.handshake.headers.authorization?.replace('Bearer ', '')
    if (!token) {
      return next(new Error('未提供认证令牌'))
    }
    
    const user = await authenticateSocket(token)
    if (!user) {
      return next(new Error('认证失败'))
    }
    
    socket.userId = user.userId
    socket.username = user.username
    next()
  } catch (error) {
    next(new Error('认证失败'))
  }
})

chatNamespace.on('connection', (socket) => {
  console.log(`聊天客户端连接: ${socket.id} (用户: ${socket.username})`)
  
  // 加入聊天房间（基于contextType和contextId）
  socket.on('joinRoom', async ({ contextType, contextId }) => {
    try {
      if (!contextType || !contextId) {
        socket.emit('error', { message: 'contextType 和 contextId 必填' })
        return
      }

      // 验证用户权限
      if (contextType === 'c2c_trade') {
        const trade = db.prepare('SELECT buyer_id, seller_id FROM c2c_trades WHERE trade_id = ?').get(contextId)
        if (!trade) {
          socket.emit('error', { message: '交易不存在' })
          return
        }
        if (trade.buyer_id !== socket.userId && trade.seller_id !== socket.userId) {
          socket.emit('error', { message: '无权加入此聊天' })
          return
        }
      }

      const roomId = `${contextType}:${contextId}`
      socket.join(roomId)
      console.log(`用户 ${socket.username} 加入房间: ${roomId}`)
      socket.emit('roomJoined', { contextType, contextId, roomId })
    } catch (error) {
      socket.emit('error', { message: error.message })
    }
  })

  // 离开聊天房间
  socket.on('leaveRoom', ({ contextType, contextId }) => {
    const roomId = `${contextType}:${contextId}`
    socket.leave(roomId)
    console.log(`用户 ${socket.username} 离开房间: ${roomId}`)
  })

  // 发送消息
  socket.on('sendMessage', async ({ contextType, contextId, receiverId, content, messageType = 'text' }) => {
    try {
      if (!contextType || !contextId || !receiverId || !content) {
        socket.emit('error', { message: '参数不完整' })
        return
      }

      // 验证权限
      if (contextType === 'c2c_trade') {
        const trade = db.prepare('SELECT buyer_id, seller_id FROM c2c_trades WHERE trade_id = ?').get(contextId)
        if (!trade) {
          socket.emit('error', { message: '交易不存在' })
          return
        }
        if (trade.buyer_id !== socket.userId && trade.seller_id !== socket.userId) {
          socket.emit('error', { message: '无权发送消息' })
          return
        }
        if (trade.buyer_id !== receiverId && trade.seller_id !== receiverId) {
          socket.emit('error', { message: '接收者必须是交易的参与方' })
          return
        }
      }

      // 保存消息到数据库
      const messageId = `MSG${Date.now()}${Math.random().toString(36).substr(2, 6).toUpperCase()}`
      const id = generateId()

      db.prepare(`
        INSERT INTO chat_messages (id, message_id, context_type, context_id, sender_id, receiver_id, content, message_type)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?)
      `).run(id, messageId, contextType, contextId, socket.userId, receiverId, content, messageType)

      // 获取发送者信息
      const sender = db.prepare('SELECT username FROM users WHERE id = ?').get(socket.userId)
      const receiver = db.prepare('SELECT username FROM users WHERE id = ?').get(receiverId)

      const message = {
        messageId,
        contextType,
        contextId,
        senderId: socket.userId,
        senderUsername: sender.username,
        receiverId,
        receiverUsername: receiver.username,
        content,
        messageType,
        isRead: false,
        createdAt: new Date().toISOString()
      }

      // 广播消息到房间
      const roomId = `${contextType}:${contextId}`
      chatNamespace.to(roomId).emit('newMessage', message)

      // 确认消息已发送
      socket.emit('messageSent', message)
    } catch (error) {
      console.error('发送消息错误:', error)
      socket.emit('error', { message: error.message })
    }
  })

  // 标记消息为已读
  socket.on('markAsRead', async ({ messageId }) => {
    try {
      const message = db.prepare('SELECT * FROM chat_messages WHERE message_id = ?').get(messageId)
      if (!message || message.receiver_id !== socket.userId) {
        socket.emit('error', { message: '无权操作' })
        return
      }

      db.prepare('UPDATE chat_messages SET is_read = 1 WHERE id = ?').run(message.id)
      
      // 通知发送者消息已读
      const roomId = `${message.context_type}:${message.context_id}`
      chatNamespace.to(roomId).emit('messageRead', { messageId, readBy: socket.userId })
    } catch (error) {
      socket.emit('error', { message: error.message })
    }
  })

  // 断开连接
  socket.on('disconnect', () => {
    console.log(`聊天客户端断开: ${socket.id} (用户: ${socket.username})`)
  })
})

// 启动服务器
httpServer.listen(PORT, async () => {
    // 显示 USDT 精度配置
    console.log(`\n📊 USDT 精度配置:`)
    console.log(`   USDT_PRECISION: ${USDT_PRECISION.toLocaleString()}`)
    console.log(`   USDT_DECIMALS: ${USDT_DECIMALS}`)
    console.log(`   环境变量 USDT_PRECISION: ${process.env.USDT_PRECISION || '(使用默认值 100000000000)'}\n`)
  
    console.log(`钱包服务器运行在 http://localhost:${PORT}`)
    console.log(`Socket.IO 聊天服务已启动`)
    await loadMonitoringAddresses()
})

export default app

